# 编写python程序 move_double.py --src 文件夹 --des 文件夹 
## 扫描--src文件夹下所有文件，并生成文件hash值，方法如下：
## 参考下面的 def hash_file()
## 从--src文件夹复制文件到 --des文件夹
## 如果存在hash值相同的文件，那么只复制最后一个被扫描到的文件到--des

#!/usr/bin/env python3
# move_double.py

import os
import sys
import hashlib
import argparse
import shutil
from pathlib import Path

def hash_file(file_path):
    """计算文件的SHA256哈希值"""
    hasher = hashlib.sha256()
    with open(file_path, 'rb') as f:
        buf = f.read()
        hasher.update(buf)
    return hasher.hexdigest()

def main():
    parser = argparse.ArgumentParser(description="扫描源文件夹，按哈希去重后复制到目标文件夹，相同哈希只保留最后一个。")
    parser.add_argument('--src', required=True, help='源文件夹路径')
    parser.add_argument('--des', required=True, help='目标文件夹路径')
    
    args = parser.parse_args()

    src_folder = Path(args.src)
    des_folder = Path(args.des)

    # 检查源文件夹是否存在
    if not src_folder.exists():
        print(f"错误：源文件夹不存在: {src_folder}", file=sys.stderr)
        sys.exit(1)

    if not src_folder.is_dir():
        print(f"错误：源路径不是一个文件夹: {src_folder}", file=sys.stderr)
        sys.exit(1)

    # 创建目标文件夹
    des_folder.mkdir(parents=True, exist_ok=True)

    # 存储哈希值 -> 文件路径（最后出现的）
    hash_map = {}

    # 遍历所有文件
    for file_path in src_folder.rglob('*'):
        if file_path.is_file():
            try:
                file_hash = hash_file(file_path)
                # 更新哈希表：后出现的覆盖前面的
                hash_map[file_hash] = file_path
            except Exception as e:
                print(f"跳过文件（读取失败）: {file_path} | 错误: {e}")

    # 开始复制，只复制每个哈希的最后一个文件
    print(f"共发现 {len(hash_map)} 个唯一哈希文件，开始复制到: {des_folder}")
    
    for file_hash, src_file in hash_map.items():
        try:
            # 计算目标路径，保持目录结构
            rel_path = src_file.relative_to(src_folder)
            dst_file = des_folder / rel_path

            # 创建目标目录
            dst_file.parent.mkdir(parents=True, exist_ok=True)

            # 复制文件
            shutil.copy2(src_file, dst_file)
            print(f"已复制: {src_file} -> {dst_file}")

        except Exception as e:
            print(f"复制失败: {src_file} -> {dst_file} | 错误: {e}")

    print("完成：去重复制操作已结束。")

if __name__ == '__main__':
    main()